package cn.liangxxhu.rocketmq.core;

import cn.liangxxhu.rocketmq.core.param.RocketmqFailedMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 失败消息数据访问层，负责将重试超限的消息持久化到数据库
 */
@Slf4j
@RequiredArgsConstructor
public class FailedMessageDao {

    // SQL常量提取，便于维护和修改
    private static final String INSERT_FAILED_MESSAGE_SQL = "INSERT INTO rocketmq_failed_message " +
            "(message_uuid, topic, tag, `keys`, event_name, " +
            "message_body, reconsume_times, fail_reason, " +
            "send_timestamp, create_time) " +
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

    private final JdbcTemplate jdbcTemplate;

    /**
     * 保存失败消息到数据库
     *
     * @param message 失败消息实体
     * @throws IllegalArgumentException 入参校验失败时抛出
     * @throws RuntimeException         数据库操作失败时抛出（包装原始异常）
     */
    public void save(RocketmqFailedMessage message) {
        try {
            // 2. 执行入库操作
            int rows = jdbcTemplate.update(
                    INSERT_FAILED_MESSAGE_SQL,
                    message.getMessageUuid(),
                    message.getTopic(),
                    message.getTag(), // 允许为null
                    message.getKeys(), // 允许为null
                    message.getEventName(), // 允许为null
                    message.getMessageBody(),
                    message.getReconsumeTimes(),
                    message.getFailReason(), // 允许为null
                    message.getSendTimestamp(), // 允许为null
                    message.getCreateTime()
            );

            // 3. 入库结果日志
            if (rows > 0) {
                log.info(
                        "失败消息入库成功 | UUID: {} | 主题: {} | 重试次数: {}",
                        message.getMessageUuid(),
                        message.getTopic(),
                        message.getReconsumeTimes()
                );
            } else {
                log.warn(
                        "失败消息入库未生效 | UUID: {} | 主题: {}（可能已存在或数据库异常）",
                        message.getMessageUuid(),
                        message.getTopic()
                );
            }
        } catch (Exception e) {
            // 4. 捕获数据库异常并包装
            String errorMsg = String.format(
                    "失败消息入库失败 | UUID: %s | 主题: %s",
                    message.getMessageUuid(),
                    message.getTopic()
            );
            log.error(errorMsg, e);
            // 包装为运行时异常，避免上层处理受检异常
            throw new RuntimeException(errorMsg, e);
        }
    }
}
